package com.example.chat.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.chat.enums.Code;
import com.example.chat.pojo.dto.UserDTO;
import com.example.chat.pojo.bo.User;
import com.example.chat.mapper.UserMapper;
import com.example.chat.pojo.res.ResModel;
import com.example.chat.service.UserService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.chat.util.DateUtils;
import com.example.chat.util.JwtUtils;
import com.example.chat.util.MD5Utils;
import com.example.chat.util.RedisIdWorker;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.Duration;

import static com.example.chat.constants.RedisConstants.USER_TOKEN_KEY;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 林邵晨
 * @since 2023-04-07
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisIdWorker redisIdWorker;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 注册
     * @param userDTO
     * @return
     */
    @Override
    public ResModel register(UserDTO userDTO) {
        if (StrUtil.isNotEmpty(userDTO.getUsername()) && StrUtil.isNotEmpty(userDTO.getPassword())){
            User dbUser = userMapper.selectByUsername(userDTO.getUsername());
            if (dbUser == null){
                User user = BeanUtil.copyProperties(userDTO, User.class);
                String salt = DateUtils.getSalt();
                user.setPassword(MD5Utils.encryption(userDTO.getPassword() + salt));
                user.setSalt(salt);
                user.setCid(String.valueOf(redisIdWorker.nextId("user")));
                userMapper.insert(user);
                user.setPassword(null);
                user.setSalt(null);
                String token = JwtUtils.createJWT(JSONUtil.toJsonStr(user));
                redisTemplate.opsForValue().set(USER_TOKEN_KEY + token,JSONUtil.toJsonStr(user), Duration.ofMinutes(30));
                return ResModel.success(Code.REGISTRATION,user).add("token",token);
            }
        }
        return ResModel.error(Code.REGISTERED);
    }

    /**
     * 登录
     * @param userDTO
     * @return
     */
    @Override
    public ResModel login(UserDTO userDTO) {
        if (StrUtil.isNotEmpty(userDTO.getUsername()) && StrUtil.isNotEmpty(userDTO.getPassword())){
            User dbUser = userMapper.selectByUsername(userDTO.getUsername());
            if (dbUser != null){
                String password = dbUser.getPassword();
                if (MD5Utils.encryption(userDTO.getPassword() + dbUser.getSalt()).equals(password)){
                    dbUser.setPassword(null);
                    dbUser.setSalt(null);
                    String token = JwtUtils.createJWT(JSONUtil.toJsonStr(dbUser));
                    redisTemplate.opsForValue().set(USER_TOKEN_KEY + token,JSONUtil.toJsonStr(dbUser), Duration.ofMinutes(30));
                    return ResModel.success(Code.LOGIN,dbUser).add("token",token);
                }
            }
        }
        return ResModel.error(Code.UN_LOGIN);
    }

    /**
     * 查询用户信息
     * @param cid
     * @return
     */
    @Override
    public ResModel getProfile(String cid) {
        User user = null;
        if (StrUtil.isNotEmpty(cid)){
            user = userMapper.selectByCid(cid);
        }
        return ResModel.success(Code.SUCCESS,user);
    }

    /**
     * 修改用户信息
     * @param user
     * @return
     */
    @Override
    public ResModel updateProfile(User user) {
        if (user != null){
            userMapper.updateById(user);
        }
        return ResModel.success(Code.UPDATE);
    }

    /**
     * 验证用户cid是否存在
     * @param id
     * @return
     */
    @Override
    public boolean checkUser(String id) {
        boolean flag = false;
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(true,User::getCid,id);
        User user = getOne(wrapper);
        if (user != null && StrUtil.isNotEmpty(user.getCid())){
            flag = true;
        }
        return flag;
    }
}
